/* Comunicación entre procesos mediante colas de mensajes */
/* Ejecuta el programa 3 */
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
/* Definición de la clave de la cola */
#define M_1 1

int crearcola(int key); /* Variables globales */

char *nombre="P3"; /* nombre dado al ejecutable del programa 3 */

int main(void)
{
int msg1,i;
pid_t pid;
char *av[2];
struct msgbuf {
	long mtype;
	char mtext [1];
	} time_msg;
int status;

/* Llamada a la función de creación de colas */
	msg1=crearcola(M_1);

/* Inicialización de los campos de la estructura */
	time_msg.mtype=1;
	time_msg.mtext[0]=0;

/* Creación de un proceso hijo */
	switch(pid = fork()){
		case (pid_t) -1:
			perror("fork");
			exit(EXIT_FAILURE);
		case (pid_t) 0:
			av[0]=nombre;
			av[1]=(char *)0;/* Puntero a un null */
/* Ejecución de un proceso imagen */
			if(execve(nombre,av,(char *)0) == -1){
				perror("execve");
				exit(EXIT_FAILURE);
			}
		default:
/* El proceso padre envía un mensaje a la cola cada segundo */
			for (i=0;i<10;i++){
/* Espera de un segundo */
				sleep(1);
				time_msg.mtext[0]++;
/* Envío de mensajes a la cola */
				if(msgsnd(msg1,&time_msg,sizeof(time_msg.mtext[0]),0)== -1){
					perror("msgsnd");
					exit(EXIT_FAILURE);
				}
			}
	}

/* El proceso padre espera la finalización del proceso hijo */
	wait(&status);
/* int msgctl(int msg, int cmd, struct msqid_ds * buf): proporciona diversos modos de control
sobre la cola de mensaje msg. La operación queda definida por cmd:
IPC_RMID, borra la cola.
el tercer parámetro es una estructura con diversos campos tales como, permisos, número de
mensajes encolados, etc. */
/* Borrado de la cola de mensajes */
	if (msgctl(msg1,IPC_RMID,(struct msqid_ds *)0) == -1) {
		perror("msgctl");
	}
exit(EXIT_SUCCESS);
}

/* Función que proporciona el identificador de la cola de mensaje */
int crearcola(int key)
{
int msgqid;
/* int msgget(int ident, int flag): proporciona un identificador para la cola de clave ident, con
permisos flag (máscara de bits) */
	switch(msgqid = msgget(key, IPC_CREAT|0666)){
/* IPC_CREAT, instrucción al sistema para crear la cola si todavía no existe */
		case -1:
			perror("msgget");
			exit(EXIT_FAILURE);
		default:
			return msgqid;
	}
}

